﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Imagine;
using Microsoft.Xna.Framework.Net;

namespace Carmack
{
    class NetworkManager
    {
        NetworkManager()
        {
            m_reader            = new PacketReader();
            m_writer            = new PacketWriter();
            m_gamePlayParams    = new NetworkSessionProperties();
        }

        #region Private_Parts
        static NetworkManager       instance;
        NetworkSession              m_session;
        PacketReader                m_reader;
        PacketWriter                m_writer;
        NetworkSessionProperties    m_gamePlayParams;    //For GamePlayInitProperties
        #endregion
        
        static public NetworkManager Instance()
        {
            if(instance == null)
                instance = new NetworkManager();
            return instance;
        }
        
        /// <summary>
        /// Broadcasts local player's data and other necessary stats to all other players
        /// </summary>
        public void BroadcastData()
        {
            EncodeData();
            foreach (LocalNetworkGamer gamer in Session.LocalGamers)                                         
                gamer.SendData( m_writer, SendDataOptions.InOrder );           
        }

        /// <summary>
        /// Recieves remote player's data and other necessay stats
        /// </summary>
        public void InterceptData()
        {
            foreach (LocalNetworkGamer gamer in NetworkManager.Instance().Session.LocalGamers)
            {
                while (gamer.IsDataAvailable)
                {
                    NetworkGamer sender;
                    gamer.ReceiveData(m_reader, out sender);

                    if (sender.IsLocal)
                        continue;                    

                    DecodeData( sender.Gamertag );
                }
            }
        }

        public void DecodeData(string senderGamerTag)
        {                        
            CRemoteHero remoteHero;
            if ( GameManager.Instance().IdentifyHero( senderGamerTag, out remoteHero ) )
                remoteHero.DecodePacket(m_reader);
        }

        public void EncodeData()
        {
            GameManager.Instance().MyHero.EncodePacket( ref m_writer);
        }

        //I know what my game is, so i need a single type of session, at least for now 
        public void CreateSession()
        {
            //Will have to put into Try{}Catch{} block
            m_session = NetworkSession.Create(NetworkSessionType.SystemLink/*Lan Play*/, 2, 8, 1, m_gamePlayParams); 
            HookEventHandlers(m_session);
        }

        public void HookEventHandlers(NetworkSession session)
        {
            //Hook Some Event Handlers
            session.GamerJoined += GamerJoinedEventHandler; 
        }

        public NetworkSessionProperties GamePlayParams
        {
            get { return m_gamePlayParams;    }
            set { m_gamePlayParams = value;   }
        }

        //For Now just do this, will crate specialized functions later on
        public NetworkSession Session
        {
            get { return m_session;     }
            set { m_session = value;    }
        }

        public PacketReader PacketReader
        {
            get { return m_reader; }
        }

        public PacketWriter PacketWriter
        {
            get { return m_writer; }
        }
        
        void GamerJoinedEventHandler(object sender, GamerJoinedEventArgs e)
        {
            GameManager.Instance().CreateHero(e.Gamer.Gamertag, e.Gamer.IsLocal);
        }


    }
}
